#include "RTMediaSource.h"

#include "DataSource.h"
#include "DataSourceMgr.h"
#include "SdpParser.h"
#include "MediaTransport.h"
#include "MyIO.h"

CRTMediaSource::CRTMediaSource()
: CMediaSource()
{
	m_isNeedRtpInfo = FALSE;
	m_isNeedReg = TRUE;
	m_pDataSource = NULL;
}

CRTMediaSource::~CRTMediaSource()
{
	OutputDebugString("CRTMediaSource::~CRTMediaSource\n");
	if(m_pDataSource)
	{
		OutputDebugString("CRTMediaSource::~CRTMediaSource,m_pDataSource->UnRegMediaSource\n");
		if(!m_isNeedReg)
			m_pDataSource->UnRegMediaSource(this);

		OutputDebugString("CRTMediaSource::~CRTMediaSource,FreeDataSource\n");
		CDataSourceMgr::GetInstance()->FreeDataSource(m_pDataSource);
	}
	OutputDebugString("CRTMediaSource::~CRTMediaSource,exit\n");
}

Bool CRTMediaSource::Initialize(CBusinessDNA &inBusinessDNA, CMediaTransport *pTransport)
{
	Assert(inBusinessDNA.GetServiceType() == P_RTSP);
	
	if(!CMediaSource::Initialize(inBusinessDNA,pTransport))
		return FALSE;

	if(m_pDataSource != NULL)
		return TRUE;
	
	m_pDataSource = CDataSourceMgr::GetInstance()->GetDataSource(m_cBusinessDNA);

	//DO NOT need to initialize DataSource, since this class is used for RTSP
	return m_pDataSource != NULL;
}
	
Bool CRTMediaSource::GetSDP(std::string *outSDP, const char * vLocalIP)
{
	Assert(m_pDataSource);
	
	if(!outSDP)
		return FALSE;
	
	if(!m_pDataSource->GetSDP(outSDP))
		return FALSE;
	
	//	throw "todo";
	//parser sdp
	CSdpParser cParser;
	cParser.SetAndParser(*outSDP);
	
	//get range
	string strTimeType;
	m_nRangeTime = (UInt64)(cParser.GetRange(strTimeType) * 1000);

	CSdpMediaAnnounceItem *pMediaItem = NULL;
	for(Int32 i=0; i<cParser.GetTrackNum(); i++)
	{
		pMediaItem = cParser.GetMediaAnnounceItem(i);
		_RtpInfo rtpInfo;
		memset(&rtpInfo, 0, sizeof(rtpInfo));
		rtpInfo.TrackID = pMediaItem->GetTrackID();
		rtpInfo.SSRC = rand();
		rtpInfo.IsSet = FALSE;
		m_RtpInfos[rtpInfo.TrackID] = rtpInfo;
	}

	return TRUE;
}

Bool CRTMediaSource::AddTrack(UInt32 inTrackID,UInt32& v_SSRC)
{
	_RtpInfosMapIterator it = m_RtpInfos.find(inTrackID);
	if(it != m_RtpInfos.end())
	{
		//found
		v_SSRC = it->second.SSRC;
		return TRUE;
	}
	else
		return FALSE;

}

ERRCODE CRTMediaSource::Seek(UInt64  vStartTime, Bool isSureKeyFrame)
{
	if(m_pDataSource && m_isNeedReg)
	{
		m_isNeedReg = FALSE;
		m_pDataSource->RegMediaSource(this);
	}

	//clear rtpinfo
	_RtpInfosMapIterator it;
	for(it = m_RtpInfos.begin(); it != m_RtpInfos.end(); ++it)
		it->second.IsSet = FALSE;

	m_isNeedRtpInfo = TRUE;
	
	//wait for rtpinfo ready
	const UInt32 iInterval = 100;
	const UInt32 iWaitTime = 30000;
	for(UInt32 i = 0; i<iWaitTime / iInterval; ++i)
	{
		if(!m_isNeedRtpInfo)
		{
			return OS_NoErr;
		}
		OS::Sleep(iInterval);
	}
	return OS_Err;
}

Bool CRTMediaSource::GetCurrentRtpInfo(UInt32 inTrackID,UInt16& outSeqNo,UInt32& outRtpTime)
{
	_RtpInfosMapIterator it = m_RtpInfos.find(inTrackID);
	if(it != m_RtpInfos.end())
	{
		//found
		outSeqNo = it->second.SeqNo;
		outRtpTime = it->second.RtpTime;
		return TRUE;
	}
	else
		return FALSE;
}
	
Int32 CRTMediaSource::DoSendPackets(UInt32 inTrackID,char * inMediaData, UInt32 inMediaDataLen, FRAME_TYPE vFrameType)
{
	if(m_pMediaTransport)
	{
		if(!m_isNeedRtpInfo)
			m_pMediaTransport->DoSendPackets(inTrackID,inMediaData,inMediaDataLen,vFrameType);
		else
		{
			//get rtpinfo
			UInt32 iCount = m_RtpInfos.size();

			_RtpInfosMapIterator it;
			for(it = m_RtpInfos.begin(); it != m_RtpInfos.end(); ++it)
			{
				if(it->first == inTrackID)
				{
					if(!it->second.IsSet)
					{
						it->second.IsSet = TRUE;
						ParserRTPPacket(inMediaData,inMediaDataLen, it->second.SeqNo, it->second.RtpTime);
						iCount--;						

						Output<<"RtpInfo: Track:"<<it->first<<" SeqNo:"<<it->second.SeqNo<<" TimeStamp:"<<it->second.RtpTime<<Endl;
					}
					m_pMediaTransport->DoSendPackets(inTrackID,inMediaData,inMediaDataLen,vFrameType);
				}
				else
				{
					if(it->second.IsSet)
						iCount--;
				}
			}

			//OK all track rtpinfos are got
			if(iCount == 0)
				m_isNeedRtpInfo = FALSE;
		}
	}
	return OS_NoErr;
}

Bool CRTMediaSource::IsValid()
{
	if( m_pDataSource && m_pDataSource->IsStopped() )
		return FALSE;
	return TRUE;
}
